﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SocketControl.Protocol.Http.Expand;
using SocketControl.Protocol.Http.General;
using SocketControl.Protocol.Http.Model;
using SocketControl.Protocol.Http.Model.General;

namespace SocketControl.Protocol.Http.ResponseMessage
{
    public class Base : GeneralHead, IResponse
    {
        #region first line
        private string httpversion;
        private string status_code;
        private string reason_phrase;
        #endregion

        #region local fileds
        private string accept_Ranges;
        private string age;
        private string etag;
        private string proxy_authenticate;
        private string retry_after;
        private string server;
        private string trailer;
        private string vary;
        private string warning;
        private string www_authenticate;
        private string location;
        private string setcookie;
        private string expires;
        #endregion

        #region Serialize
        Func<string, HttpVersion> HttpVersion = delegate (string param)
        {
            switch (param.ToLower())
            {
                case "http/1.0": { return Model.General.HttpVersion.Http1_0; }
                case "http/1.1": { return Model.General.HttpVersion.Http1_1; }
                default: { return default(Model.General.HttpVersion); }
            }
        };
        Func<string, int> StatusCode = delegate (string args) { return !args.IsNull() ? int.Parse(args) : 500; };
        Func<string, string> ReasonPhrase = delegate (string args) { return !args.IsNull() ? args : "error"; };
        Func<string, string> AcceptRanges = delegate (string args) { return args; };
        Func<string, string> Age = delegate (string args) { return args; };
        Func<string, string> ETag = delegate (string args) { return args; };
        Func<string, string> ProxyAuthenticate = delegate (string args) { return args; };
        Func<string, string> RetryAfter = delegate (string args) { return args; };
        Func<string, string> Server = delegate (string args) { return args; };
        Func<string, string> Trailer = delegate (string args) { return args; };
        Func<string, string> Vary = delegate (string args) { return args; };
        Func<string, string> Warning = delegate (string args) { return args; };
        Func<string, string> WWWAuthenticate = delegate (string args) { return args; };
        Func<string, string> Location = delegate (string args) { return args; };
        Func<string, string> Set_Cookie = delegate (string args) { return args; };
        Func<string, string> Expires = delegate (string args) { return args; };
        private Model.Response Serialize(Model.GeneralHeadModel args)
        {
            return new Model.Response(args)
            {
                StatusCode = StatusCode(this.status_code),
                ReasonPhrase = ReasonPhrase(this.reason_phrase),
                AcceptRanges = AcceptRanges(this.accept_Ranges),
                Age = Age(this.age),
                ETag = ETag(this.etag),
                ProxyAuthenticate = ProxyAuthenticate(this.proxy_authenticate),
                RetryAfter = RetryAfter(this.retry_after),
                Server = Server(this.server),
                Trailer = Trailer(this.trailer),
                Vary = Vary(this.vary),
                Warning = Warning(this.warning),
                WWWAuthenticate = WWWAuthenticate(this.www_authenticate),
                Location = Location(this.location),
                Setcookie = Set_Cookie(this.setcookie),
                Expires = Expires(this.expires)
            };
        }

        #endregion

        #region DeSerialize
        Func<Model.Response, string> DeHttpVersion = delegate (Model.Response param)
        {
            switch (param.HttpVersion)
            {
                case Model.General.HttpVersion.Http1_0: { return "HTTP/1.0"; }
                case Model.General.HttpVersion.Http1_1: { return "HTTP/1.1"; }
                default: { return "HTTP/1.1"; }
            }
        };
        Func<Model.Response, string> DeStatusCode = delegate (Model.Response args) { return args.StatusCode > 0 ? args.StatusCode.ToString() : "500"; };
        Func<Model.Response, string> DeReasonPhrase = delegate (Model.Response args) { return args.ReasonPhrase.ToString(); };
        Func<Model.Response, string> DeAcceptRanges = delegate (Model.Response args) { return args.AcceptRanges; };
        Func<Model.Response, string> DeAge = delegate (Model.Response args) { return args.Age; };
        Func<Model.Response, string> DeETag = delegate (Model.Response args) { return args.ETag; };
        Func<Model.Response, string> DeProxyAuthenticate = delegate (Model.Response args) { return args.ProxyAuthenticate; };
        Func<Model.Response, string> DeRetryAfter = delegate (Model.Response args) { return args.RetryAfter; };
        Func<Model.Response, string> DeServer = delegate (Model.Response args) { return args.Server; };
        Func<Model.Response, string> DeTrailer = delegate (Model.Response args) { return args.Trailer; };
        Func<Model.Response, string> DeVary = delegate (Model.Response args) { return args.Vary; };
        Func<Model.Response, string> DeWarning = delegate (Model.Response args) { return args.Warning; };
        Func<Model.Response, string> DeWWWAuthenticate = delegate (Model.Response args) { return args.WWWAuthenticate; };
        Func<Model.Response, string> DeLocation = delegate (Model.Response args) { return args.Location; };
        Func<Model.Response, string> DeSet_Cookie = delegate (Model.Response args) { return args.Setcookie; };
        Func<Model.Response, string> DeExpires = delegate (Model.Response args) { return args.Expires; };
        private void DeSerialize(Model.Response args)
        {
            this.httpversion = DeHttpVersion(args);
            this.status_code = DeStatusCode(args);
            this.reason_phrase = DeReasonPhrase(args);
            this.accept_Ranges = DeAcceptRanges(args);
            this.age = DeAge(args);
            this.etag = DeETag(args);
            this.proxy_authenticate = DeProxyAuthenticate(args);
            this.retry_after = DeRetryAfter(args);
            this.server = DeServer(args);
            this.trailer = DeTrailer(args);
            this.vary = DeVary(args);
            this.warning = DeWarning(args);
            this.www_authenticate = DeWWWAuthenticate(args);
            this.location = DeLocation(args);
            this.setcookie = DeSet_Cookie(args);
            this.expires = DeExpires(args);
        }
        #endregion

        #region Method
        protected string GetHttpVersion { get { return this.httpversion; } }
        public string GetMessageString(Model.Response args = null)
        {
            if (args != null)
            {
                this.DeSerialize(args);
                base.GetMessageString(args.GetGeneralBody());
            }
            string result = string.Empty;
            #region get http response first line
            if (!this.httpversion.IsNull()) { result.JoinAfterWithSpace(this.GetHttpVersion, out result); }
            if (!this.status_code.IsNull()) { result.JoinAfterWithSpace(this.status_code, out result); }
            if (!this.reason_phrase.IsNull()) { result.JoinAfterWithCRLF(this.reason_phrase, out result); }
            #endregion
            #region get http response body
            if (!this.accept_Ranges.IsNull()) { result.JoinAfterWithCRLF("Accept-Ranges:" + this.accept_Ranges, out result); }
            if (!this.age.IsNull()) { result.JoinAfterWithCRLF("Age:" + this.age, out result); }
            if (!this.etag.IsNull()) { result.JoinAfterWithCRLF("ETag:" + this.etag, out result); }
            if (!this.proxy_authenticate.IsNull()) { result.JoinAfterWithCRLF("Proxy-Authenticate:" + this.proxy_authenticate, out result); }
            if (!this.retry_after.IsNull()) { result.JoinAfterWithCRLF("Retry-After:" + this.retry_after, out result); }
            if (!this.server.IsNull()) { result.JoinAfterWithCRLF("Server:" + this.server, out result); }
            if (!this.trailer.IsNull()) { result.JoinAfterWithCRLF("Trailer:" + this.trailer, out result); }
            if (!this.vary.IsNull()) { result.JoinAfterWithCRLF("Vary:" + this.vary, out result); }
            if (!this.warning.IsNull()) { result.JoinAfterWithCRLF("Warning:" + this.warning, out result); }
            if (!this.www_authenticate.IsNull()) { result.JoinAfterWithCRLF("WWW-Authenticate:" + this.www_authenticate, out result); }
            if (!this.location.IsNull()) { result.JoinAfterWithCRLF("Location:" + this.location, out result); }
            if (!this.setcookie.IsNull()) { result.JoinAfterWithCRLF("Set-Cookie:" + this.setcookie, out result); }
            if (!this.expires.IsNull()) { result.JoinAfterWithCRLF("Expires:" + this.expires, out result); }
            #endregion
            result.JoinAfterWithCRLF(base.GetMessageString(), out result);
            return result;
        }

        public new Model.Response GetInstance()
        {
            return Serialize(base.GetInstance());
        }

        public new Model.Response GetInstance(string args)
        {
            AnalysisMessage(args);
            return Serialize(base.GetInstance(args));
        }

        private void AnalysisMessage(string args)
        {
            int line = 0;
            foreach (string o in args.ReadLine())
            {
                if (line == 0)
                {
                    string[] param = o.Split(' ');
                    if (param.Length == 3)
                    {
                        this.httpversion = param[0];
                        this.status_code = param[1];
                        this.reason_phrase = param[2];
                    }
                }
                else
                {
                    string[] param = AnalysisLine(o);
                    switch (param[0].ToLower())
                    {
                        case "accept-Ranges": { this.accept_Ranges = param[1]; break; }
                        case "age": { this.age = param[1]; break; }
                        case "etag": { this.etag = param[1]; break; }
                        case "proxy-authenticate": { this.proxy_authenticate = param[1]; break; }
                        case "retry-after": { this.retry_after = param[1]; break; }
                        case "server": { this.server = param[1]; break; }
                        case "trailer": { this.trailer = param[1]; break; }
                        case "vary": { this.vary = param[1]; break; }
                        case "warning": { this.warning = param[1]; break; }
                        case "www-authenticate": { this.www_authenticate = param[1]; break; }
                        case "location": { this.location = param[1]; break; }
                        case "set-cookie": { this.setcookie = param[1]; break; }
                        case "expires":
                            {
                                this.expires = param[1]; break;
                            }
                    }
                }
                ++line;
            }
        }
    }

    #endregion
}

